package at.jaki.ubb.crawling.appThreads;

import org.apache.log4j.Logger;

import at.jaki.ubb.crawling.core.Constants;

/**
 * Abstract class that implements the common part of every own thread started by
 * the Crawling engine.
 * 
 * @author Attila Jakabfi
 * 
 */
abstract class AbstractCrawlerThread implements Runnable {

	private static final Logger LOG = Logger.getLogger(AbstractCrawlerThread.class);

	/**
	 * the thread can be stopped by setting this flag to false.
	 */
	private boolean running = false;

	/**
	 * this thread can be stopped by setting this flag to true.
	 */
	private boolean stop = false;

	@Override
	protected final Object clone() throws CloneNotSupportedException {
		throw new CloneNotSupportedException("Singeltone can not be cloned");
	}

	@Override
	public void run() {
		if (running) {
			LOG.error("This thread is already running: " + this.getClass().getName());
			return;
		}
		try {
			running = true;
			LOG.info("Starting " + this.getClass().getName());
			stop = false;

			while (true) {
				if (stop) {
					break;
				}
				doWork();
				try {
					Thread.sleep(Constants.CHECKER_SLEEP_PERIOD);
				} catch (InterruptedException e) {
					LOG.warn("Sleep interrupted " + e.getMessage());
				}
			}

		} finally {
			running = false;
		}
	}

	/**
	 * Will stop this thread. <strong> if clear is true, then the waiting task
	 * list will be cleared and all elements destroyed.</strong>
	 * 
	 * @param use false is the thread will be restarted later. Use true if it's
	 *        a final shutdown.
	 */
	public synchronized void stop(boolean clear) {
		if (clear) {
			clear();
		}
		stop = true;
	}

	/**
	 * @return true if the thread is running
	 */
	public boolean isRunning() {
		return running;
	}

	/**
	 * this method will be called if the stop method is called with the
	 * <code>clear</code> flag.
	 */
	protected abstract void clear();

	/**
	 * This method should contain the logic of the thread. The method will be
	 * many times while the application is running.
	 */
	protected abstract void doWork();

}
